/**
 * 账本管理路由模块
 * 
 * 主要功能：
 * 1. 账本CRUD操作（创建、查询、更新、删除）
 * 2. 账本分享功能（生成分享码、加入账本）
 * 3. 账本成员管理（查询成员、移除成员）
 * 
 * 权限控制：
 * - 所有接口都需要JWT Token认证
 * - 所有者权限：修改账本、删除账本、生成分享码、管理成员
 * - 成员权限：查看账本、添加记录、退出账本
 * 
 * @author 个人预算管理系统开发团队
 * @date 2025-10-26
 */

// ==================== 依赖导入 ====================
const express = require('express');                    // Express框架
const router = express.Router();                       // 创建路由实例
const { authenticateToken } = require('../middleware/auth'); // JWT认证中间件
const db = require('../config/database');              // 数据库连接池

// ==================== 全局中间件 ====================

/**
 * 应用认证中间件到所有路由
 * 
 * @description 所有账本相关操作都需要用户登录
 * 使用router.use()在路由级别应用中间件
 * 所有后续的路由都会先经过authenticateToken验证
 */
router.use(authenticateToken);

// ==================== 获取账本列表接口 ====================

/**
 * 获取我的账本列表
 * 
 * @route GET /api/books
 * @access Private - 需要JWT Token认证
 * 
 * @description 获取用户拥有的账本和加入的共享账本列表
 * 
 * @param {object} req.user - JWT Token解析出的用户信息
 * @param {number} req.user.user_id - 用户ID
 * 
 * @returns {object} 200 - 成功响应
 * @returns {number} 200.code - 状态码 200
 * @returns {array} 200.data - 账本数组
 * @returns {number} 200.data[].book_id - 账本ID
 * @returns {string} 200.data[].book_name - 账本名称
 * @returns {string} 200.data[].book_type - 账本类型
 * @returns {string} 200.data[].icon - 账本图标
 * @returns {string} 200.data[].color - 主题颜色
 * @returns {string} 200.data[].owner_nickname - 所有者昵称
 * @returns {string} 200.data[].my_role - 我的角色（owner/member）
 * @returns {number} 200.data[].member_count - 成员数量
 * 
 * @example
 * // 请求示例
 * GET /api/books
 * Authorization: Bearer <token>
 * 
 * // 响应示例
 * {
 *   "code": 200,
 *   "data": [
 *     {
 *       "book_id": 1,
 *       "book_name": "我的账本",
 *       "book_type": "personal",
 *       "icon": "💰",
 *       "color": "#4285f4",
 *       "owner_nickname": "张三",
 *       "my_role": "owner",
 *       "member_count": 1
 *     },
 *     {
 *       "book_id": 2,
 *       "book_name": "家庭账本",
 *       "my_role": "member",
 *       "member_count": 3
 *     }
 *   ]
 * }
 * 
 * SQL查询设计思路：
 * 1. 使用UNION逻辑：我拥有的账本 OR 我加入的账本
 * 2. LEFT JOIN users：获取所有者昵称
 * 3. LEFT JOIN book_members：获取我的角色
 * 4. CASE WHEN：动态判断角色（所有者或成员）
 * 5. 子查询COUNT：统计成员数量（+1包含所有者）
 * 6. DISTINCT：避免重复结果
 * 7. ORDER BY created_at DESC：最新创建的排在前面
 */
router.get('/', async (req, res) => {
    try {
        // 1. 从JWT Token获取用户ID
        const userId = req.user.user_id;
        
        // 2. 查询账本列表（复杂SQL查询）
        // 查询逻辑：
        //  - b.owner_user_id = ? : 我创建的账本
        //  - bm.user_id = ? : 我加入的账本
        // 通过LEFT JOIN关联users表获取所有者昵称
        // 通过LEFT JOIN关联book_members表获取成员信息
        const [books] = await db.query(`
            SELECT DISTINCT b.*,                         -- 账本所有字段
                   u.nickname as owner_nickname,         -- 所有者昵称
                   CASE 
                       WHEN b.owner_user_id = ? THEN 'owner'  -- 如果是所有者，角色为owner
                       ELSE bm.role                      -- 否则使用book_members表中的角色
                   END as my_role,                       -- 我的角色
                   (SELECT COUNT(*) FROM book_members WHERE book_id = b.book_id) + 1 as member_count  -- 成员数（+1算上所有者）
            FROM account_books b                         -- 主表：account_books
            LEFT JOIN users u ON b.owner_user_id = u.user_id  -- 关联用户表获取所有者信息
            LEFT JOIN book_members bm ON b.book_id = bm.book_id AND bm.user_id = ?  -- 关联成员表
            WHERE b.owner_user_id = ? OR bm.user_id = ?  -- 筛选条件：我拥有的或我加入的
            ORDER BY b.created_at DESC                   -- 按创建时间倒序
        `, [userId, userId, userId, userId]);
        
        // 3. 返回账本列表
        res.json({
            code: 200,
            data: books
        });
        
    } catch (error) {
        // 4. 错误处理
        console.error('获取账本列表错误:', error);
        res.status(500).json({ 
            code: 500, 
            message: '获取失败', 
            error: error.message 
        });
    }
});

// ==================== 创建账本接口 ====================

/**
 * 创建新账本
 * 
 * @route POST /api/books
 * @access Private - 需要JWT Token认证
 * 
 * @description 创建一个新的账本
 * 
 * @param {object} req.body - 请求体
 * @param {string} req.body.book_name - 账本名称（必填）
 * @param {string} req.body.book_type - 账本类型（选填，默认personal）
 * @param {string} req.body.description - 描述（选填）
 * @param {string} req.body.icon - 图标（选填，默认📔）
 * @param {string} req.body.color - 主题颜色（选填，默认#4285f4）
 * 
 * @returns {object} 201 - 创建成功响应
 * @returns {number} 201.code - 状态码 201
 * @returns {string} 201.message - 成功消息
 * @returns {object} 201.data - 账本数据
 * @returns {number} 201.data.book_id - 新账本ID
 * @returns {string} 201.data.book_name - 账本名称
 * @returns {string} 201.data.book_type - 账本类型
 * @returns {string} 201.data.icon - 图标
 * @returns {string} 201.data.color - 颜色
 * 
 * @returns {object} 400 - 参数错误
 * @returns {object} 500 - 服务器错误
 * 
 * @example
 * // 请求示例
 * POST /api/books
 * Authorization: Bearer <token>
 * {
 *   "book_name": "家庭账本",
 *   "book_type": "family",
 *   "icon": "🏠",
 *   "color": "#34a853"
 * }
 * 
 * // 响应示例
 * {
 *   "code": 201,
 *   "message": "账本创建成功",
 *   "data": {
 *     "book_id": 2,
 *     "book_name": "家庭账本",
 *     "book_type": "family",
 *     "icon": "🏠",
 *     "color": "#34a853"
 *   }
 * }
 * 
 * 设计思路：
 * 1. 自动设置owner_user_id为当前登录用户
 * 2. 提供默认值（type、icon、color），简化创建流程
 * 3. 返回完整的账本信息，便于前端立即使用
 */
router.post('/', async (req, res) => {
    try {
        // 1. 从请求体获取账本信息
        const { book_name, book_type, description, icon, color } = req.body;
        
        // 2. 从JWT Token获取用户ID
        // 当前用户自动成为账本所有者
        const userId = req.user.user_id;
        
        // 3. 验证必填项
        if (!book_name) {
            return res.status(400).json({ 
                code: 400, 
                message: '请输入账本名称' 
            });
        }
        
        // 4. 插入账本到数据库
        // 使用 || 运算符提供默认值：
        //  - book_type默认'personal'（个人账本）
        //  - icon默认'📔'（笔记本图标）
        //  - color默认'#4285f4'（蓝色）
        const [result] = await db.query(`
            INSERT INTO account_books (owner_user_id, book_name, book_type, description, icon, color)
            VALUES (?, ?, ?, ?, ?, ?)
        `, [
            userId, 
            book_name, 
            book_type || 'personal',   // 默认个人账本
            description, 
            icon || '📔',              // 默认笔记本图标
            color || '#4285f4'         // 默认蓝色
        ]);
        
        // 5. 返回创建成功响应
        // 状态码201表示"Created"（资源已创建）
        res.status(201).json({
            code: 201,
            message: '账本创建成功',
            data: {
                book_id: result.insertId,                // 新账本的自增ID
                book_name,
                book_type: book_type || 'personal',
                icon: icon || '📔',
                color: color || '#4285f4'
            }
        });
        
    } catch (error) {
        // 6. 错误处理
        console.error('创建账本错误:', error);
        res.status(500).json({ 
            code: 500, 
            message: '创建失败', 
            error: error.message 
        });
    }
});

// 创建新账本
router.post('/', async (req, res) => {
    try {
        const { book_name, book_type, description, icon, color } = req.body;
        const userId = req.user.user_id;
        
        if (!book_name) {
            return res.status(400).json({ code: 400, message: '请输入账本名称' });
        }
        
        const [result] = await db.query(`
            INSERT INTO account_books (owner_user_id, book_name, book_type, description, icon, color)
            VALUES (?, ?, ?, ?, ?, ?)
        `, [userId, book_name, book_type || 'personal', description, icon || '📔', color || '#4285f4']);
        
        res.status(201).json({
            code: 201,
            message: '账本创建成功',
            data: {
                book_id: result.insertId,
                book_name,
                book_type: book_type || 'personal',
                icon: icon || '📔',
                color: color || '#4285f4'
            }
        });
    } catch (error) {
        console.error('创建账本错误:', error);
        res.status(500).json({ code: 500, message: '创建失败', error: error.message });
    }
});

// ==================== 生成分享码接口 ====================

/**
 * 生成账本分享码
 * 
 * @route POST /api/books/:bookId/share
 * @access Private - 需要JWT Token认证
 * 
 * @description 为账本生成分享码，其他用户可通过分享码加入该账本
 * 
 * @param {object} req.params - 路径参数
 * @param {string} req.params.bookId - 账本ID
 * @param {object} req.user - JWT Token解析出的用户信息
 * @param {number} req.user.user_id - 用户ID
 * 
 * @returns {object} 200 - 生成成功响应
 * @returns {number} 200.code - 状态码 200
 * @returns {string} 200.message - 成功消息
 * @returns {object} 200.data - 分享数据
 * @returns {string} 200.data.share_code - 分享码（6位大写字母+数字）
 * @returns {string} 200.data.share_url - 分享链接
 * 
 * @returns {object} 403 - 权限不足（非所有者）
 * @returns {object} 500 - 服务器错误
 * 
 * @example
 * // 请求示例
 * POST /api/books/1/share
 * Authorization: Bearer <token>
 * 
 * // 响应示例
 * {
 *   "code": 200,
 *   "message": "分享码生成成功",
 *   "data": {
 *     "share_code": "A1B2C3",
 *     "share_url": "http://yourbudget.com/join/A1B2C3"
 *   }
 * }
 * 
 * 分享码生成算法：
 * 1. 使用Math.random()生成随机数（0-1之间）
 * 2. toString(36)转为36进制字符串（0-9, a-z）
 * 3. substring(2, 8)截取6位字符（跳过"0."前缀）
 * 4. toUpperCase()转为大写
 * 结果：6位大写字母+数字的组合，如：A1B2C3
 * 
 * 设计思路：
 * 1. 6位分享码，36^6 = 21亿种组合，碰撞概率极低
 * 2. 大写字母便于用户识别和输入
 * 3. 分享码存储在数据库，确保唯一性
 * 4. 设置is_shared=1标记账本为共享状态
 */
router.post('/:bookId/share', async (req, res) => {
    try {
        // 1. 从路径参数获取账本ID
        const { bookId } = req.params;
        
        // 2. 从JWT Token获取用户ID
        const userId = req.user.user_id;
        
        // 3. 权限验证：检查是否是账本所有者
        // 只有所有者才能生成分享码，成员无此权限
        const [books] = await db.query(
            'SELECT * FROM account_books WHERE book_id = ? AND owner_user_id = ?',
            [bookId, userId]
        );
        
        // 如果查询结果为空，说明用户不是所有者
        if (books.length === 0) {
            return res.status(403).json({ 
                code: 403, 
                message: '只有账本所有者可以生成分享码' 
            });
        }
        
        // 4. 生成唯一分享码（6位随机字符）
        // 算法详解：
        // Math.random() → 生成0-1之间的随机数，如：0.123456789
        // .toString(36) → 转为36进制字符串，如："0.4fzyo82mvyr"
        // .substring(2, 8) → 截取第2-8位，即跳过"0."，取6位字符："4fzyo8"
        // .toUpperCase() → 转为大写："4FZYO8"
        const shareCode = Math.random().toString(36).substring(2, 8).toUpperCase();
        
        // 5. 更新账本：保存分享码并标记为共享状态
        // is_shared=1：标记账本开启分享
        // share_code：存储分享码
        await db.query(`
            UPDATE account_books 
            SET is_shared = 1, share_code = ? 
            WHERE book_id = ?
        `, [shareCode, bookId]);
        
        // 6. 返回成功响应
        res.json({
            code: 200,
            message: '分享码生成成功',
            data: {
                share_code: shareCode,                           // 分享码
                share_url: `http://yourbudget.com/join/${shareCode}`  // 分享链接（可配置）
            }
        });
        
    } catch (error) {
        // 7. 错误处理
        console.error('生成分享码错误:', error);
        res.status(500).json({ 
            code: 500, 
            message: '生成失败', 
            error: error.message 
        });
    }
});

// ==================== 加入账本接口 ====================

/**
 * 通过分享码加入账本
 * 
 * @route POST /api/books/join
 * @access Private - 需要JWT Token认证
 * 
 * @description 用户输入分享码，加入他人的共享账本
 * 
 * @param {object} req.body - 请求体
 * @param {string} req.body.share_code - 分享码（必填，6位字符）
 * @param {object} req.user - JWT Token解析出的用户信息
 * @param {number} req.user.user_id - 用户ID
 * 
 * @returns {object} 200 - 加入成功响应
 * @returns {number} 200.code - 状态码 200
 * @returns {string} 200.message - 成功消息
 * @returns {object} 200.data - 账本信息
 * @returns {number} 200.data.book_id - 账本ID
 * @returns {string} 200.data.book_name - 账本名称
 * @returns {string} 200.data.book_type - 账本类型
 * @returns {string} 200.data.icon - 图标
 * 
 * @returns {object} 400 - 参数错误或试图加入自己的账本
 * @returns {object} 404 - 分享码无效
 * @returns {object} 409 - 已加入该账本
 * @returns {object} 500 - 服务器错误
 * 
 * @example
 * // 请求示例
 * POST /api/books/join
 * Authorization: Bearer <token>
 * {
 *   "share_code": "A1B2C3"
 * }
 * 
 * // 响应示例
 * {
 *   "code": 200,
 *   "message": "加入账本成功",
 *   "data": {
 *     "book_id": 2,
 *     "book_name": "家庭账本",
 *     "book_type": "family",
 *     "icon": "🏠"
 *   }
 * }
 * 
 * 业务流程：
 * 1. 验证分享码格式
 * 2. 查找对应的账本
 * 3. 验证账本是否开启分享
 * 4. 检查是否是账本所有者（不能加入自己的账本）
 * 5. 检查是否已加入（避免重复加入）
 * 6. 插入成员记录
 * 
 * 设计思路：
 * 1. 分享码统一转大写，避免大小写问题
 * 2. 多重验证，保证数据完整性
 * 3. 角色默认为'member'，区别于所有者
 */
router.post('/join', async (req, res) => {
    try {
        // 1. 从请求体获取分享码
        const { share_code } = req.body;
        
        // 2. 从JWT Token获取用户ID
        const userId = req.user.user_id;
        
        // 3. 验证分享码是否为空
        if (!share_code) {
            return res.status(400).json({ 
                code: 400, 
                message: '请输入分享码' 
            });
        }
        
        // 4. 通过分享码查找账本
        // toUpperCase()：统一转为大写，避免大小写差异
        // is_shared = 1：确保账本开启了分享功能
        const [books] = await db.query(
            'SELECT * FROM account_books WHERE share_code = ? AND is_shared = 1',
            [share_code.toUpperCase()]
        );
        
        // 5. 验证分享码是否有效
        if (books.length === 0) {
            return res.status(404).json({ 
                code: 404, 
                message: '分享码无效或账本未开启分享' 
            });
        }
        
        const book = books[0];
        
        // 6. 检查是否是账本所有者
        // 设计考虑：所有者不需要加入自己的账本
        // 避免在成员表中出现所有者的记录（所有者在account_books表中）
        if (book.owner_user_id === userId) {
            return res.status(400).json({ 
                code: 400, 
                message: '这是您自己的账本' 
            });
        }
        
        // 7. 检查是否已加入该账本
        // 避免重复加入，导致数据重复
        const [existing] = await db.query(
            'SELECT * FROM book_members WHERE book_id = ? AND user_id = ?',
            [book.book_id, userId]
        );
        
        if (existing.length > 0) {
            return res.status(409).json({ 
                code: 409, 
                message: '您已经加入了这个账本' 
            });
        }
        
        // 8. 插入成员记录
        // role='member'：标识为普通成员（区别于所有者）
        await db.query(
            'INSERT INTO book_members (book_id, user_id, role) VALUES (?, ?, ?)',
            [book.book_id, userId, 'member']
        );
        
        // 9. 返回成功响应
        // 返回账本基本信息，便于前端显示
        res.json({
            code: 200,
            message: '加入账本成功',
            data: {
                book_id: book.book_id,
                book_name: book.book_name,
                book_type: book.book_type,
                icon: book.icon
            }
        });
        
    } catch (error) {
        // 10. 错误处理
        console.error('加入账本错误:', error);
        res.status(500).json({ 
            code: 500, 
            message: '加入失败', 
            error: error.message 
        });
    }
});

// ==================== 获取成员列表接口 ====================

/**
 * 获取账本成员列表
 * 
 * @route GET /api/books/:bookId/members
 * @access Private - 需要JWT Token认证
 * 
 * @description 查询账本的所有成员（包括所有者和普通成员）
 * 
 * @param {object} req.params - 路径参数
 * @param {string} req.params.bookId - 账本ID
 * @param {object} req.user - JWT Token解析出的用户信息
 * @param {number} req.user.user_id - 用户ID
 * 
 * @returns {object} 200 - 查询成功响应
 * @returns {number} 200.code - 状态码 200
 * @returns {array} 200.data - 成员数组
 * @returns {number} 200.data[].user_id - 用户ID
 * @returns {string} 200.data[].username - 用户名
 * @returns {string} 200.data[].nickname - 昵称
 * @returns {string} 200.data[].avatar_url - 头像URL
 * @returns {string} 200.data[].role - 角色（owner/member）
 * @returns {string} 200.data[].joined_at - 加入时间
 * 
 * @returns {object} 403 - 无权访问
 * @returns {object} 500 - 服务器错误
 * 
 * @example
 * // 请求示例
 * GET /api/books/1/members
 * Authorization: Bearer <token>
 * 
 * // 响应示例
 * {
 *   "code": 200,
 *   "data": [
 *     {
 *       "user_id": 1,
 *       "username": "zhangsan",
 *       "nickname": "张三",
 *       "avatar_url": null,
 *       "role": "owner",
 *       "joined_at": "2025-10-01T10:00:00.000Z"
 *     },
 *     {
 *       "user_id": 2,
 *       "username": "lisi",
 *       "nickname": "李四",
 *       "avatar_url": null,
 *       "role": "member",
 *       "joined_at": "2025-10-05T15:30:00.000Z"
 *     }
 *   ]
 * }
 * 
 * SQL查询设计：
 * 1. UNION查询：合并所有者和成员两个来源的数据
 * 2. 第一部分：从account_books获取所有者信息
 * 3. 第二部分：从book_members获取普通成员信息
 * 4. JOIN users：关联用户表获取详细信息
 * 5. ORDER BY joined_at：按加入时间排序（所有者最早）
 */
router.get('/:bookId/members', async (req, res) => {
    try {
        // 1. 从路径参数获取账本ID
        const { bookId } = req.params;
        
        // 2. 从JWT Token获取用户ID
        const userId = req.user.user_id;
        
        // 3. 权限验证：检查用户是否有权访问该账本
        // 使用UNION查询：
        //  - 第一部分：检查是否是所有者
        //  - 第二部分：检查是否是成员
        // SELECT 1：只返回标识，不需要具体数据，提高效率
        const [access] = await db.query(`
            SELECT 1 FROM account_books WHERE book_id = ? AND owner_user_id = ?
            UNION
            SELECT 1 FROM book_members WHERE book_id = ? AND user_id = ?
        `, [bookId, userId, bookId, userId]);
        
        // 如果没有查询结果，说明用户既不是所有者也不是成员
        if (access.length === 0) {
            return res.status(403).json({ 
                code: 403, 
                message: '无权访问此账本' 
            });
        }
        
        // 4. 查询成员列表（包括所有者）
        // 使用UNION合并两部分数据：
        //  - 第一部分：从account_books查询所有者
        //  - 第二部分：从book_members查询普通成员
        // 确保返回的字段结构一致
        const [members] = await db.query(`
            SELECT u.user_id, u.username, u.nickname, u.avatar_url, 
                   'owner' as role, b.created_at as joined_at
            FROM account_books b
            JOIN users u ON b.owner_user_id = u.user_id
            WHERE b.book_id = ?
            UNION
            SELECT u.user_id, u.username, u.nickname, u.avatar_url, 
                   bm.role, bm.joined_at
            FROM book_members bm
            JOIN users u ON bm.user_id = u.user_id
            WHERE bm.book_id = ?
            ORDER BY joined_at                                  -- 按加入时间排序，所有者最早
        `, [bookId, bookId]);
        
        // 5. 返回成员列表
        res.json({
            code: 200,
            data: members
        });
        
    } catch (error) {
        // 6. 错误处理
        console.error('获取成员列表错误:', error);
        res.status(500).json({ 
            code: 500, 
            message: '获取失败', 
            error: error.message 
        });
    }
});

// ==================== 删除账本接口 ====================

/**
 * 删除账本
 * 
 * @route DELETE /api/books/:bookId
 * @access Private - 需要JWT Token认证
 * 
 * @description 删除指定账本（仅所有者可操作）
 * 
 * @param {object} req.params - 路径参数
 * @param {string} req.params.bookId - 账本ID
 * @param {object} req.user - JWT Token解析出的用户信息
 * @param {number} req.user.user_id - 用户ID
 * 
 * @returns {object} 200 - 删除成功响应
 * @returns {number} 200.code - 状态码 200
 * @returns {string} 200.message - 成功消息
 * 
 * @returns {object} 403 - 权限不足（非所有者）
 * @returns {object} 500 - 服务器错误
 * 
 * @example
 * // 请求示例
 * DELETE /api/books/1
 * Authorization: Bearer <token>
 * 
 * // 响应示例
 * {
 *   "code": 200,
 *   "message": "账本删除成功"
 * }
 * 
 * 重要提示：
 * 1. 删除操作不可逆，前端应有二次确认
 * 2. 级联删除：账本、记录、成员、预算等关联数据都会被删除
 * 3. 建议在删除前提供数据导出功能
 * 
 * 级联删除说明：
 * - records表：通过外键ON DELETE CASCADE自动删除该账本的所有记录
 * - book_members表：自动删除该账本的所有成员关系
 * - budgets表：自动删除该账本的所有预算设置
 * 
 * 数据库设计：
 * CREATE TABLE records (
 *   ...
 *   FOREIGN KEY (book_id) REFERENCES account_books(book_id) ON DELETE CASCADE
 * );
 */
router.delete('/:bookId', async (req, res) => {
    try {
        // 1. 从路径参数获取账本ID
        const { bookId } = req.params;
        
        // 2. 从JWT Token获取用户ID
        const userId = req.user.user_id;
        
        // 3. 权限验证：检查是否是账本所有者
        // 只有所有者才能删除账本，成员无此权限
        const [books] = await db.query(
            'SELECT * FROM account_books WHERE book_id = ? AND owner_user_id = ?',
            [bookId, userId]
        );
        
        // 如果查询结果为空，说明用户不是所有者
        if (books.length === 0) {
            return res.status(403).json({ 
                code: 403, 
                message: '只有所有者可以删除账本' 
            });
        }
        
        // 4. 删除账本
        // 注意：这会触发级联删除
        //  - records表中该账本的所有记录被删除
        //  - book_members表中该账本的所有成员关系被删除
        //  - budgets表中该账本的所有预算被删除
        // 这是通过外键约束ON DELETE CASCADE实现的
        await db.query('DELETE FROM account_books WHERE book_id = ?', [bookId]);
        
        // 5. 返回成功响应
        res.json({
            code: 200,
            message: '账本删除成功'
        });
        
    } catch (error) {
        // 6. 错误处理
        console.error('删除账本错误:', error);
        res.status(500).json({ 
            code: 500, 
            message: '删除失败', 
            error: error.message 
        });
    }
});

// ==================== 导出路由 ====================

/**
 * 导出账本路由模块
 * 
 * @exports router - Express路由实例
 * 
 * 包含的路由：
 * - GET / - 获取账本列表
 * - POST / - 创建账本
 * - POST /:bookId/share - 生成分享码
 * - POST /join - 加入账本
 * - GET /:bookId/members - 获取成员列表
 * - DELETE /:bookId - 删除账本
 * 
 * 权限说明：
 * - 所有路由都需要认证（JWT Token）
 * - 生成分享码、删除账本：仅所有者
 * - 查看成员：所有者和成员
 * - 查看账本、加入账本：所有用户
 */
module.exports = router; 